package com.colbby.datahouse.transform;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.colbby.datahouse.utils.TypeDescriptor;

public class ObjectTransformer implements DataTypeTransform<Object> {
	
	private static final ObjectTransformer t = new ObjectTransformer();
	private List<DataTypeTransform<?>> list = new ArrayList<>();
	
	private ObjectTransformer() {
		list.add(BooleanTransformer.INSTANCE);
		list.add(ByteTransformer.INSTANCE);
		list.add(CharTransformer.INSTANCE);
		list.add(DateTransformer.INSTANCE);
		list.add(DoubleTransformer.INSTANCE);
		list.add(EnumTransformer.INSTANCE);
		list.add(FloatTransformer.INSTANCE);
		list.add(IntTransformer.INSTANCE);
		list.add(LongTransformer.INSTANCE);
		list.add(ShortTransformer.INSTANCE);
		list.add(StringTransformer.INSTANCE);
	}
	
	public static DataTypeTransform<?> getDirectedTransformer() {
		return t;
	}
	
	public static void main(String[] args) {
		System.out.println(new ObjectTransformer().transform(new TypeDescriptor(Integer.class), "1"));
	}

	@Override
	public Object transform(TypeDescriptor returnType, Object value) {
		if(value == null) return null;
		DataTypeTransform<?> transformer = choose(returnType, value);
		if(transformer == null) {
			return doElse(returnType, value);
		}
		return transformer.transform(returnType, value);
	}
	
	private Object doElse(TypeDescriptor returnType, Object value) {
		Class<?> clazz = value.getClass();
		if(value instanceof Iterable) {
			 Iterator<?> it = ((Iterable<?>) value).iterator();
			 return it.hasNext() ? transform(returnType, it.next()) : null; 
		} else if(clazz.isArray()) {
			return Array.getLength(value) > 0 ? transform(returnType, Array.get(value, 0)) : null;
		}
		return value;
	}
	
	private DataTypeTransform<?> choose(TypeDescriptor returnType, Object value) {
		for(DataTypeTransform<?> transformer : list) {
			if(transformer.shouldDo(returnType, value)) {
				return transformer;
			}
		}
		return null;
	}

	@Override
	public boolean shouldDo(TypeDescriptor returnType, Object value) {
		return true;
	}
}
